package br.com.loteria.lotofacil;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.TreeMap;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

public class Lotofacil {
	private FileResultadosLotofacil fileResultadosLotofacil = new FileResultadosLotofacil();
	private List<Concurso> concursoList = new ArrayList<Concurso>();

	public void fazerDownloadDoArquivo() throws IOException {
		fileResultadosLotofacil.fazerDownload();
	}

	public void preencherConcursoListAtravezDoArquivo() throws IOException {
		try (FileInputStream im = new FileInputStream(fileResultadosLotofacil)) {
			try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
				int byteLido;
				while ((byteLido = im.read()) > -1) {
					byteArrayOutputStream.write(byteLido);
				}

				Elements elementsVariasTR = Jsoup.parse(byteArrayOutputStream.toString()).select(Utils.TAG_TBODY).select(Utils.TAG_TR);
				for (Element elementTR : elementsVariasTR.subList(1, elementsVariasTR.size())) {
					Elements elementsVariasTD = elementTR.select(Utils.TAG_TD);

					Concurso concurso = new Concurso();
					concurso.setNumeroConcurso(Integer.parseInt(elementsVariasTD.get(0).text()));
					concurso.setDataSorteio(Utils.stringToLocalDate(elementsVariasTD.get(1).text()));
					for (Element elementNumeroDaBolaTD : elementsVariasTD.subList(2, 17)) {
						concurso.getNumeroBolaList().add(Integer.parseInt(elementNumeroDaBolaTD.text()));
					}

					getConcursoList().add(concurso);
				}
			}
		}
	}

	public Map<Integer, Integer> calcularQuantidadeNumerosIguais(List<Concurso> concursosEscolhidos) {
		Map<Integer, Integer> numerosLotofacil = new LinkedHashMap<Integer, Integer>();
		while (numerosLotofacil.size() < 25) {
			numerosLotofacil.put(numerosLotofacil.size() + 1, 0);
		}

		for (Concurso concurso : concursosEscolhidos) {
			for (Integer numero : concurso.getNumeroBolaList()) {
				numerosLotofacil.put(numero, numerosLotofacil.get(numero) + 1);
			}
		}

		return numerosLotofacil;
	}

	public Map<Integer, Integer> ordenarCalculoQuantidadeNumerosIguais(final Map<Integer, Integer> numerosLotofacil) {
		SortedMap<Integer, Integer> numerosLotofacilOrdenado = new TreeMap<Integer, Integer>(new Comparator<Integer>() {
			@Override
			public int compare(Integer o1, Integer o2) {
				Integer v1 = numerosLotofacil.get(o1);
				Integer v2 = numerosLotofacil.get(o2);
				int returned = v2.compareTo(v1);

				if (returned == 0) {
					returned = -1;
					// returned = new Random().nextInt() >= 0 ? 1 : -1;
				}
				return returned;
			}
		});

		for (Entry<Integer, Integer> entry : numerosLotofacil.entrySet()) {
			numerosLotofacilOrdenado.put(entry.getKey(), entry.getValue());
		}

		return numerosLotofacilOrdenado;
	}

	public List<Concurso> getConcursoList() {
		return concursoList;
	}

	public List<Concurso> estrategia01(List<Concurso> concursosEscolhidos) {
		Map<Integer, Integer> calculoOrdenadoQuantidadeNumerosIguais = ordenarCalculoQuantidadeNumerosIguais(calcularQuantidadeNumerosIguais(concursosEscolhidos));
		List<Integer> numerosQueMaisSairam = Arrays.asList(calculoOrdenadoQuantidadeNumerosIguais.keySet().toArray(new Integer[] {}));

		List<Concurso> palpiteDeJogosList = new ArrayList<Concurso>();

		int i = 1;
		while (i <= 16) {
			Concurso concurso = new Concurso();
			for (Integer numero : numerosQueMaisSairam) {
				int casaDeDezena = numerosQueMaisSairam.indexOf(numero) + 1;
				if (casaDeDezena == i || casaDeDezena == i + 1 || casaDeDezena == i + 2 || concurso.getNumeroBolaList().size() >= 15) {
					continue;
				}
				concurso.getNumeroBolaList().add(numero);
			}
			Collections.sort(concurso.getNumeroBolaList());
			palpiteDeJogosList.add(concurso);
			i++;
		}

		printarNoConsole(palpiteDeJogosList);

		return palpiteDeJogosList;
	}

	private void printarNoConsole(List<Concurso> concursoList) {
		for (Concurso concurso : concursoList) {
			StringBuilder sb = new StringBuilder();
			for (Integer numero : concurso.getNumeroBolaList()) {
				sb.append(new DecimalFormat("00").format(numero) + ", ");
			}
			System.out.println(sb.toString());
		}
		System.out.println();
	}
}
